package org.overtheair.say.logic;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;
import org.overtheair.say.common.GlobalHelper;
import org.overtheair.say.domain.DataUpcomingEvent;
import org.overtheair.say.domain.QueryType;


public class DataProviderUpcoming
	extends DataProviderAncestor
{
	
	//*************************************************************************
	// public methods
	//*************************************************************************

	
	/**
	 * Return a set of Upcoming events in the place specified
	 * @param locality
	 * 
	 * @return
	 */
	public static List<DataUpcomingEvent> getUpcomingEvents(String location)
	{
		return getUpcomingEvents(QueryType.FixedLocation, location, 0, 0);
	}

	/**
	 * Return a set of Upcoming events near coordinates
	 * @param latitude
	 * @param longitude
	 * 
	 * @return
	 */
	public static List<DataUpcomingEvent> getUpcomingEvents(double latitude, double longitude)
	{
		return getUpcomingEvents(QueryType.CurrentLocation, "", latitude, longitude);
	}
	



	
	//*************************************************************************
	// private methods
	//*************************************************************************

	/**
	 * @param queryType 1: search by coordinates, 2 search by location
	 */
	
	private static List<DataUpcomingEvent> getUpcomingEvents(
			QueryType queryType,
			String location,
			double latitude,
			double longitude)
	{
		List<DataUpcomingEvent> listResult;
		int accuracy;
		String upcomingUrl;
		
		listResult = new ArrayList<DataUpcomingEvent>();
		
		//accuracy
	    //Recorded accuracy level of the location information.
		// World level is 1, Country is ~3, Region ~6, City ~11, Street ~16. Current range is 1-16. The default is 16.
		
		//make a first try with street accuracy
		accuracy = 16;
		while (true)
		{
			//set webservice query
			if (queryType == QueryType.CurrentLocation)
				upcomingUrl = getUpcomingUrlForCoordinates(latitude, longitude, accuracy);
			else
				upcomingUrl = getUpcomingUrlForLocation(location, accuracy);
				
			//try to get info from webservice
			WebserviceRequestClient wsClient = new WebserviceRequestClient();
			String webResult = wsClient.RequestGET(upcomingUrl);
			
			if (GlobalHelper.IsNullOrEmpty(webResult))
				return listResult;
			
			//detach the main part of the reply
			JSONArray jsonArrayOfEvents = detachDataPartFromYQLWebserviceReply(webResult, "event");
			//and extract photo objects from it
			if (null == jsonArrayOfEvents)
				return listResult;

			//refines searches based on accuracy, but only for coordinate search
			if (queryType == QueryType.CurrentLocation)
			{
				//check for number of photos
				if (16 == accuracy && jsonArrayOfEvents.length() < MAX_RESULTS)
				{
					//retry with more accuracy
					accuracy = 13;
					continue;
				}
				
				//check for number of photos
				if (13 == accuracy && jsonArrayOfEvents.length() < MAX_RESULTS)
				{
					//retry with much more accuracy
					accuracy = 11;
					continue;
				}
			}
			
			//final try, scrape what can find
			for (int i = 0; i < jsonArrayOfEvents.length(); i++) {
				JSONObject upcomingEvent = jsonArrayOfEvents.optJSONObject(i);
				if (null != upcomingEvent)
					listResult.add(new DataUpcomingEvent(upcomingEvent.toString()));
			}
			break;
		}

		return listResult;
	}

	/**
	 * Get the url for upcoming webservice to get photos by latitude and longitude
	 */
	private static String getUpcomingUrlForCoordinates(double latitude, double longitude, int accuracy)
	{

		//original YQL
		//select * from upcoming.events where woeid in
		//  (select woeid from geo.places.neighbors where neighbor_woeid in
		//    (select place.woeid from flickr.places where lat=51.5 and lon=0 and accuracy=13))
		//      limit 20
		//url
		//http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20upcoming.events%20where%20woeid%20in%20(select%20woeid%20from%20geo.places.neighbors%20where%20neighbor_woeid%20in%20(select%20place.woeid%20from%20flickr.places%20where%20lat%3D51.5%20and%20lon%3D0%20and%20accuracy%3D13))%20limit%2020%0A&format=json&diagnostics=false&callback=
		
		String newUrl =
			replaceLatitudeLongitudeAccuracyLimitgetUpcoming(
				"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20upcoming.events%20where%20woeid%20in%20(select%20woeid%20from%20geo.places.neighbors%20where%20neighbor_woeid%20in%20(select%20place.woeid%20from%20flickr.places%20where%20lat%3D##latitude##%20and%20lon%3D##longitude##%20and%20accuracy%3D##accuracy##))%20limit%20##limit##%0A&format=json&diagnostics=false&callback=",
				latitude,
				longitude,
				accuracy,
				MAX_RESULTS
			);
		return newUrl;
	}


	/**
	 * Get the url for upcoming webservice to get photos by location
	 */
	private static String getUpcomingUrlForLocation(String location, int accuracy)
	{
		//original yql
		//select * from upcoming.events where woeid in
		//  (select woeid from geo.places.neighbors where neighbor_woeid in
		//		    (select woeid from flickr.places where query="Roma, Italy"))
		//		limit 20
		//url
		//http://query.yahooapis.com/v1/yql?q=select%20*%20from%20upcoming.events%20where%20woeid%20in%20(select%20woeid%20from%20geo.places.neighbors%20where%20neighbor_woeid%20in%20(select%20woeid%20from%20flickr.places%20where%20query%3D%22Roma%2C%20Italy%22))%20limit%2020%0A%0A&format=json&diagnostics=false&callback=

		String newUrl =
			replaceLocationAndLimit(
				"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20upcoming.events%20where%20woeid%20in%20(select%20woeid%20from%20geo.places.neighbors%20where%20neighbor_woeid%20in%20(select%20woeid%20from%20flickr.places%20where%20query%3D%22##location##%22))%20limit%20##limit##&format=json&diagnostics=false&callback=",
				location,
				MAX_RESULTS
			);
		return newUrl;
	}
}
